package draft

import (
	"container/list"
	"sync"
)

// Cache 草稿缓存接口
type Cache interface {
	Set(key string, value *Draft)
	Get(key string) (*Draft, bool)
	Delete(key string)
	GetOrCreate(key string, width, height int) *Draft
}

// LRUCache 基于LRU算法的草稿缓存
type LRUCache struct {
	capacity int
	cache    map[string]*list.Element
	list     *list.List
	mutex    sync.RWMutex
}

// cacheItem 缓存项
type cacheItem struct {
	key   string
	value *Draft
}

// NewLRUCache 创建新的LRU缓存
func NewLRUCache(capacity int) *LRUCache {
	return &LRUCache{
		capacity: capacity,
		cache:    make(map[string]*list.Element),
		list:     list.New(),
	}
}

// Set 设置缓存项
func (c *LRUCache) Set(key string, value *Draft) {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	// 如果键已存在，删除旧项
	if elem, ok := c.cache[key]; ok {
		c.list.Remove(elem)
		delete(c.cache, key)
	}

	// 如果缓存已满，删除最久未使用的项
	if c.list.Len() >= c.capacity {
		oldest := c.list.Back()
		if oldest != nil {
			c.list.Remove(oldest)
			oldItem := oldest.Value.(cacheItem)
			delete(c.cache, oldItem.key)
		}
	}

	// 添加新项到缓存
	elem := c.list.PushFront(cacheItem{key: key, value: value})
	c.cache[key] = elem
}

// Get 获取缓存项
func (c *LRUCache) Get(key string) (*Draft, bool) {
	c.mutex.RLock()
	elem, ok := c.cache[key]
	c.mutex.RUnlock()

	if !ok {
		return nil, false
	}

	c.mutex.Lock()
	defer c.mutex.Unlock()

	// 将访问的项移到列表前端
	c.list.MoveToFront(elem)
	return elem.Value.(cacheItem).value, true
}

// Delete 删除缓存项
func (c *LRUCache) Delete(key string) {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if elem, ok := c.cache[key]; ok {
		c.list.Remove(elem)
		delete(c.cache, key)
	}
}

// GetOrCreate 获取缓存项，如果不存在则创建
func (c *LRUCache) GetOrCreate(key string, width, height int) *Draft {
	// 尝试获取缓存项
	draft, ok := c.Get(key)
	if ok {
		return draft
	}

	// 创建新草稿
	newDraft := NewDraft(width, height)
	newDraft.ID = key // 使用传入的key作为草稿ID

	// 添加到缓存
	c.Set(key, newDraft)

	return newDraft
}
